﻿using System;
using Internal.Runtime.Models;
using Internal.Runtime.Services.BattleSkill;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using Runtime.Services.BattleSkill;
using UnityEngine;

namespace Runtime.Models {

    /// <summary>
    /// 技能数据
    /// </summary>
    public interface IDFR_BattleSkillModelBase : IDFR_Model {

        IDFR_BattleSkillModelBaseSetter AsSetter();

        IDFR_BattleEffectHolder AsHolder();

        /// <summary>
        /// 类型
        /// </summary>
        DFR_BattleSkillType Type { get; }

        /// <summary>
        /// 触发时机
        /// </summary>
        DFR_BattleSkillTriggerTiming TriggerTiming { get; }

        /// <summary>
        /// 触发所需攻击次数，<see cref="Type"/> 为 <see cref="DFR_BattleSkillType.AttackCount"/> 时有效
        /// </summary>
        int RequireAttackLaunchTimes { get; }

        /// <summary>
        /// 触发所需杀击的数量，<see cref="Type"/> 为 <see cref="DFR_BattleSkillType.KillCount"/> 时有效
        /// </summary>
        int RequireKillCount { get; }

        /// <summary>
        /// 实例ID
        /// </summary>
        DFR_BattleEntityInstanceID EntityInstanceID { get; }

        /// <summary>
        /// 模型资产键
        /// </summary>
        string ModelAssetKey { get; }

        /// <summary>
        /// 子弹资产键
        /// </summary>
        string BulletAssetKey { get; }

        /// <summary>
        /// 拥有者玩家ID
        /// </summary>
        DFR_BattlePlayerID OwnerPlayerID { get; }

        /// <summary>
        /// 拥有者实体实例ID
        /// </summary>
        DFR_BattleEntityInstanceID OwnerEntityInstanceID { get; }

        /// <summary>
        /// 等级
        /// </summary>
        int Level { get; }

        /// <summary>
        /// 效果数据列表
        /// </summary>
        IDFR_ReadOnlyBattleEffectListModelBase EffectList { get; }

        /// <summary>
        /// 触发几率
        /// </summary>
        IDFR_ReadOnlyBattleData TriggerProbability { get; }

        /// <summary>
        /// 触发频率
        /// </summary>
        IDFR_ReadOnlyBattleData TriggerRate { get; }
    }

    public interface IDFR_BattleSkillModelBaseSetter : IDFR_BattleSkillModelBase {

        /// <summary>
        /// 添加效果
        /// </summary>
        /// <param name="effectEntityID">效果ID</param>
        /// <param name="level">等级</param>
        void AddEffect(DFR_BattleEntityID effectEntityID, int level);

        /// <summary>
        /// 清除效果
        /// </summary>
        void ClearEffect();
    }

    public abstract class DFR_BattleSkillModelBase : DFR_Model, IDFR_BattleSkillModelBase, IDFR_BattleSkillModelBaseSetter, IDFR_BattleSkillModelBaseInternal, IDFR_BattleEffectHolder, IDFR_BattleEffectHolderSetter, IDFR_BattleEffectHolderInternal {

        public IDFR_BattleSkillModelBaseSetter AsSetter() => this;

        public IDFR_BattleEffectHolder AsHolder() => this;

        public DFR_BattleSkillType Type { get; protected set; }

        public DFR_BattleSkillTriggerTiming TriggerTiming { get; protected set; }

        public abstract int RequireAttackLaunchTimes { get; }

        public abstract int RequireKillCount { get; }

        bool IDFR_BattleEffectHolder.RequireSyncPosition => false;
        IDFR_BattleEffectHolderSetter IDFR_BattleEffectHolder.AsSetter() => throw new NotSupportedException("源数据有静态实现，不参与表现");
        void IDFR_BattleEffectHolderSetter.SetModelAssetKey(string value) => throw new NotSupportedException("源数据有静态实现，不参与表现");
        void IDFR_BattleEffectHolderSetter.SyncPositionFrom(DFR_BattleEntityInstanceID entityInstanceID) => throw new NotSupportedException("源数据有静态实现，不参与表现");
        void IDFR_BattleEffectHolderSetter.SyncPositionOnce(DFR_BattleEntityInstanceID entityInstanceID) => throw new NotSupportedException("源数据有静态实现，不参与表现");
        Vector3 IDFR_BattleEffectHolderInternal.SyncPosition() => throw new NotSupportedException("源数据有静态实现，不参与表现");

        public abstract string ModelAssetKey { get; }

        public abstract bool HasModelAsset { get; }

        public abstract string BulletAssetKey { get; }

        public DFR_BattleEntityInstanceID EntityInstanceID { get; private set; }

        public DFR_BattleEntityInstanceID OwnerEntityInstanceID { get; private set; }

        public DFR_BattlePlayerID OwnerPlayerID { get; private set; }

        public int Level { get; private set; }

        public DFR_BattleEntityHandle EntityHandle { get; private set; }
        void IDFR_BattleEffectHolderInternal.SetEntityHandle(DFR_BattleEntityHandle value) => EntityHandle = value;

        [Autowired]
        private readonly IDFR_BattleEffectListModelBase m_EffectList;
        public IDFR_ReadOnlyBattleEffectListModelBase EffectList => m_EffectList;

        [Autowired]
        private readonly IDFR_BattleData m_TriggerProbability;
        public IDFR_ReadOnlyBattleData TriggerProbability => m_TriggerProbability;

        [Autowired]
        private readonly IDFR_BattleData m_TriggerRate;
        public IDFR_ReadOnlyBattleData TriggerRate => m_TriggerRate;

        protected override void Dispose() {
            foreach (var model in m_EffectList) {
                (model as IDisposable).Dispose();
            }
            base.Dispose();
        }

        protected abstract bool Initialize();

        void IDFR_BattleSkillModelBaseInternal.Initialize(DFR_BattleEntityID entityID, DFR_BattleEntityInstanceID onwerEntityInstanceID, DFR_BattlePlayerID ownerPlayerID, int level) {
            EditBegin();
            EntityInstanceID = new DFR_BattleEntityInstanceID { ID = entityID };
            OwnerEntityInstanceID = onwerEntityInstanceID;
            OwnerPlayerID = ownerPlayerID;
            Level = level;
            if (Initialize()) {
            }
            EditDone();
        }

        public void AddEffect(DFR_BattleEntityID effectEntityID, int level) {
            if (effectEntityID != DFR_BattleEntityID.Empty) {
                var effect = KHBD.TypeMap.Instantiate<IDFR_BattleEffectModelBase>();
                (effect as IDFR_BattleEffectModelBaseInternal).Initialize(effectEntityID, this, level);
                m_EffectList.Add(effect);
            }
        }

        public void ClearEffect() {
            foreach (var effect in m_EffectList) {
                if (effect is IDisposable disposable) {
                    disposable.Dispose();
                }
            }
            m_EffectList.Clear();
        }
    }
}

namespace Internal.Runtime.Models {

    public interface IDFR_BattleSkillModelBaseInternal {

        void Initialize(DFR_BattleEntityID entityID, DFR_BattleEntityInstanceID onwerEntityInstanceID, DFR_BattlePlayerID ownerPlayerID, int level);

        DFR_BattleEntityHandle EntityHandle { get; }
    }
}
